#ifndef __GFORM_H__
#define __GFORM_H__

#ifdef CLE_NAMESPACE
namespace gui;
#endif

class GForm;

typedef struct Form_Message 
{
    uint        message;
    ulong       wParam;
    long        lParam;

    Form_Message(uint msg = 0, ulong wparam = 0 , long lparam = 0)
        :message(msg), wParam(wparam), lParam(lparam) {}
}GMessage;

class ShortCut
{
public:
    ShortCut(ushort value = 0)
        :m_value(value) {}

    ushort             getValue() const { return m_value; }
    char               getChar() const { return (char)(m_value & 0x00FF); }
    ushort             hasCtrl() const { return m_value & 0x0100; }
    ushort             hasAlt() const { return m_value & 0x0200; }
    ushort             hasShift() const { return m_value & 0x0400; }
    void               setCtrl()  { m_value |= 0x0100; }
    void               setAlt()  { m_value |= 0x0200; }
    void               setShift()  { m_value |= 0x0400; }
    void               setChar(char ch) { m_value = (m_value & 0xFF00) | ch; }
    void               reset() { m_value = 0;}
    bool               isValid() const;
private:
    ushort             m_value;
};

enum  MouseButton { NoButton = 0x00, LeftButton = 0x01, RightButton = 0x02, ShiftKey = 0x04, CtrlKey = 0x08, MidKey = 0x10 };

class GMouseEvent
{
public:
    int                buttons() const { return m_mask; }
    void               setButtons(uchar mask ) { m_mask = mask; }
    uchar              m_mask;
    GPoint             m_ptPos;
};

class GSizeEvent
{
public:
    enum  SizeType { RESTORED = 0, MINIMIZED, MAXIMIZED, MAXSHOW, MAXHIDE };

    GSize              m_Size;
    SizeType           m_type;
};

class GWheelEvent
{
public:
    
    short              m_Flag;
    short              m_Direct;
    GPoint             m_ptPos;

};

class GPaintEvent
{
public:
    GRect              m_rcPaint;
};


class GScrollEvent
{
public:
	int type;
    int oldPos;
	int pos;
	int counts;

};


class GCaret
{
public:
    GCaret(GForm* pForm, int w = 1, int h = 16);
    ~GCaret() {}
    
    void                    show() ;
    void                    hide() ;
    bool                    isShown()const { return m_bIsShown; }
    GPoint                  getPos()const { return m_ptCaret; }
    GSize                   getSize()const { return m_szCaret; }
    void                    setPos(const GPoint& pos);
    void                    setSize(const GSize& size) { if (!(m_szCaret == size)) { create(size); show();}}
private:
    bool                    create(const GSize& size);
    GPoint                  m_ptCaret;
    GSize                   m_szCaret;
    GForm*                  m_pForm;
    bool                    m_bIsShown;
};

typedef  std::vector<GString>   GDropEvent;
typedef  std::map<uint, int>    ItemsMaper;

class GForm  
{
public:
	GForm(GForm* parent = 0);
	virtual ~GForm();

    GHForm                    getHandle() const { return m_hForm; }
    void                      setHandle(GHForm handle) { if (handle == 0) return ; m_hForm = handle; addForm(this); }  //addForm
    bool                      isNull() const { return m_hForm == NULL;}

    void                      getGeometry(GRect& rcWnd) const;
    void                      setGeometry(const GRect& rcWnd) const;
    GRect                     getClientRect(GRect& rcClient = GRect()) const;
    void                      setClientRect(const GRect& rcClient) const;
    void                      resize(const GSize& size);

    GForm*                    getParent() const { return m_pParent; }
    void                      setParent(GForm* pform)  { m_pParent = pform; }

    void                      show(int cmd = 1) const;
    void                      hide() const { show(0); }
    void                      close() const;
    void                      repaint(const GRect& rc = GRect()) const;
	virtual void              setFocus(bool focused =true);

	void                      setCursor(GCursor::CursorShape cursor = GCursor::Default);

    static GForm*             mainForm() { return s_pMainForm; } 
private:
	static void               addForm( GForm* pForm);
	static void               removeForm( GForm* pForm);
public:
	static GForm*             getForm(GHForm handle);

    long                      sendMessage(const GMessage& msg) const { return sendMessageTo(this,msg); } //send message to form-self
    static  long              sendMessageTo(const GForm* pForm, const GMessage& msg); // send message to some form
    long                      callMessage(const GMessage& msg)  {  return callMessageFrom(this, msg);  } // response message directly
    static  long              callMessageFrom( GForm* pForm, const GMessage& msg);
    friend long               messageDispatch(GForm* pForm, const GMessage& msg);
    //Event
protected:
    virtual void              createEvent() { }
    virtual void              destroyEvent() {}
    virtual void              closeEvent() ;                  //tap close button on window
	virtual void              toggleEvent(int itemID) { }
    virtual void              keysDownEvent(ShortCut& sc);          
    virtual void              keysUpEvent(ShortCut& sc) {}
    virtual void              charPressEvent(wchar_t unichar, void* param = 0) {} 
    virtual void              itemEvent(int itemID, long param){ }  // command response
    virtual void              mouseDoubleClickEvent ( GMouseEvent& event ){}
    virtual void              mouseMoveEvent ( GMouseEvent& event ){}
    virtual void              mousePressEvent ( GMouseEvent& event ){}
    virtual void              mouseReleaseEvent ( GMouseEvent& event ){}
    virtual void              paintEvent ( GPaintEvent& event ){}
    virtual void              sizeEvent ( GSizeEvent& event ){}
    virtual void              wheelEvent ( GWheelEvent& event ){}
    virtual void              enterEvent ( GMouseEvent& event ){}
    virtual void              leaveEvent ( GMouseEvent& event ){}
    virtual void              dropEvent(const GDropEvent& event) {}
    virtual void              scrollEvent( GScrollEvent& event ) {}
    virtual int               messageEvent(const GMessage& msg) { return -1; }
	
	ItemsMaper                 m_shortcutMaper;
	static  GForm*             s_pMainForm;  // set in constructor of some object
private:
    GHForm                     m_hForm;
    GForm*                     m_pParent;
    

//	static  std::map<GHANDLE, GForm*>        m_vFormList;
};

#ifdef CLE_NAMESPACE
}
#endif

#endif 
